<template>
    <div :class="['editor-box', readOnly ? 'h' : '']">
        <header class="toolbar" v-if="!readOnly">
            <Nav :onlyEmojis="onlyEmojis" @onChooseEmojis="handleChooseEmojis" />
        </header>
        <QuillEditor ref="editorRef" contentType="html" class="quill-editor" :options="option" />
    </div>
</template>

<script setup lang="ts">
import {ref, h, watchEffect} from "vue";
import {Modal, Image} from "ant-design-vue";
import {Quill} from "@vueup/vue-quill";

import Nav from "./Nav.vue";
import EmojiBlot from "./formats/emoji.ts";
import {deltaToMessage} from "./utils/utils.ts";

Quill.register("formats/emoji", EmojiBlot);

interface Props {
    onlyEmojis?: boolean;
    readOnly?: boolean;
    text?: Array<any>;
}

const props = defineProps<Props>();

const {onlyEmojis = false, readOnly = false, text = []} = props;

const editorRef: any = ref();

// 粘贴 图片提示上传
function handleClipboard(node: any, Delta) {
    const ops: any[] = [];
    Delta.ops.forEach((op: any) => {
        // 如果粘贴了图片，这里会是一个对象，所以可以这样处理
        if (op.insert && typeof op.insert === "string") {
            ops.push(op);
        }
        if (op.insert && typeof op.insert?.image) {
            const src = op.insert?.image;
            Modal.confirm({
                title: "是否发送图片",
                cancelText: "取消",
                okText: "发送",
                content: h(Image, {src, width: "100%"}),
            });
        }
    });
    Delta.ops = ops;
    return Delta;
}

const getQuill = () => {
    return editorRef.value?.getQuill();
};
// 获取光标位置
const getQuillSelectionIndex = () => {
    let quill = getQuill();
    return (quill.getSelection() || {}).index || quill.getLength();
};
// 表情事件
function handleChooseEmojis(data: any) {
    if (data.type == 1) {
        const quill = getQuill();
        let index = getQuillSelectionIndex();
        if (index == 1 && quill.getLength() == 1 && quill.getText(0, 1) == "\n") {
            quill.deleteText(0, 1);
            index = 0;
        }

        if (data.img) {
            quill.insertEmbed(index, "emoji", {
                alt: data.value,
                src: data.img,
                width: "24px",
                height: "24px",
            });
        } else {
            quill.insertText(index, data.value);
        }

        quill.setSelection(index + 1, 0, "user");
    } else {
    }
}

// 发送消息
const handleSendMessage = () => {
    const quill = getQuill();
    // 获取文本内容
    var delta = quill.getContents();
    let data = deltaToMessage(delta);
    if (data.items.length === 0) {
        return;
    }

    switch (data.msgType) {
        case 1: // 文字消息
            if (data.items[0].content.length > 1024) {
                return window["$message"].info("发送内容超长，请分条发送");
            }
            //   emit(
            //     'editor-event',
            //     emitCall('text_event', data, (ok: any) => {
            //       ok && getQuill().setContents([], Quill.sources.USER)
            //     })
            //   )
            break;
    }
};

const option = {
    debug: "false",
    readOnly,
    modules: {
        toolbar: false,
        keyboard: {
            bindings: {
                enter: {
                    key: 13,
                    handler: handleSendMessage,
                },
            },
        },
        clipboard: {
            matchers: [["img", handleClipboard]],
        },
    },
    placeholder: "按Enter发送 / Shift+Enter 换行",
    theme: "snow",
};

// 获取消息
const handleGetMessage = (): string => {
    const quill = getQuill();
    const delta = quill.getContents();
    console.log("delta", JSON.stringify(delta.ops));
    let data = deltaToMessage(delta);
    const val = data?.items?.[0].content;
    return val;
};

defineExpose({
    getMessage: () => {
        return handleGetMessage();
    },
});

watchEffect(() => {
    if (text) {
        const quill = getQuill();
        quill?.setContents(text, Quill.sources.API);
    }
});
</script>

<style scoped lang="less">
.editor-box {
    height: 400px;
    display: flex;
    flex-direction: column;

    :deep(.ql-container) {
        overflow-y: scroll;
        padding-bottom: 20px;
        flex: 1;
    }
}
.h {
    min-width: 400px;
    height: max-content;

    :deep(.ql-container) {
        padding-bottom: 0 !important;
    }
}
</style>
